/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */
package com.yami.shop.security.common.manager;

import cn.hutool.crypto.symmetric.AES;
import com.yami.shop.common.exception.YamiShopBindException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Base64.Decoder;

/**
 * @author 菠萝凤梨
 * @date 2022/1/19 16:02
 */
@Component
public class PasswordManager {
    private static final Logger logger = LoggerFactory.getLogger(PasswordManager.class);

    /**
     * 用于aes签名的key，16位
     */
    @Value("${auth.password.signKey:de7579adbb767122}")
    public String passwordSignKey;

//    public String decryptPassword(String data) {
//        // 在使用oracle的JDK时，JAR包必须签署特殊的证书才能使用。
//        // 解决方案 1.使用openJDK或者非oracle的JDK（建议） 2.添加证书
//        // hutool的aes报错可以打开下面那段代码
//        // SecureUtil.disableBouncyCastle();
//        AES aes = new AES(passwordSignKey.getBytes(StandardCharsets.UTF_8));
//        String decryptStr;
//        String decryptPassword;
//        try {
//            decryptStr = aes.decryptStr(data);
//            decryptPassword = decryptStr.substring(13);
//        } catch (Exception e) {
//            logger.error("Exception:", e);
//            throw new YamiShopBindException("AES解密错误", e);
//        }
//        return decryptPassword;
//    }

    public String decryptPassword(String data) {
        try {
            String _password = decrypt(data);
            System.err.println(_password);
            return _password;
        } catch (Exception ex) {
            logger.error("Exception:", ex);
            throw new YamiShopBindException("用户名或密码输入错误", ex);
        }
    }

    private final String ALGORITHM = "AES";
    private final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
    private final long TIME_TOLERANCE = 3 * 60 * 1000; // 3分钟容忍时间（毫秒）

    /**
     * 解密方法
     * @param encryptedText 加密后的字符串，格式为 "iv:encryptedData"
     * @return 原始密码（去掉时间戳部分）
     * @throws RuntimeException 当时间戳不在有效范围内时抛出异常
     */
    public String decrypt(String encryptedText) {
        try {
            // 分割 IV 和加密数据
            String[] parts = encryptedText.split(":");
            if (parts.length < 2) {
                throw new IllegalArgumentException("Invalid encrypted text format");
            }

            String ivHex = parts[0];
            String encryptedData = parts[1];

            // 将十六进制的 IV 转换为字节数组
            byte[] iv = hexStringToByteArray(ivHex);

            // 解码 Base64 加密数据
            Decoder decoder = Base64.getDecoder();
            byte[] encryptedBytes = decoder.decode(encryptedData);

            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(passwordSignKey.getBytes("UTF-8"), ALGORITHM);
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

            // 初始化密码器
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);

            // 解密
            byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
            String decryptedText = new String(decryptedBytes, "UTF-8");

            // 解析时间戳和密码
            String[] decryptedParts = decryptedText.split(":");
            if (decryptedParts.length < 2) {
                throw new RuntimeException("用户名或密码输入错误");
            }

            String timestampStr = decryptedParts[0];
            String password = decryptedParts[1];

            // 验证时间戳
            validateTimestamp(timestampStr);

            return password;

        } catch (Exception e) {
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            }
            throw new RuntimeException("用户名或密码输入错误", e);
        }
    }

    /**
     * 验证时间戳是否在有效范围内（前后3分钟内）
     */
    private void validateTimestamp(String timestampStr) {
        try {
            long encryptedTimestamp = Long.parseLong(timestampStr);
            long currentTimestamp = System.currentTimeMillis();
            long timeDifference = Math.abs(currentTimestamp - encryptedTimestamp);

            if (timeDifference > TIME_TOLERANCE) {
                throw new RuntimeException("用户名或密码输入错误");
            }

            System.err.println("时间戳验证通过，时间差: " + (timeDifference / 1000) + "秒");

        } catch (NumberFormatException e) {
            throw new RuntimeException("用户名或密码输入错误", e);
        }
    }

    /**
     * 将十六进制字符串转换为字节数组
     */
    private byte[] hexStringToByteArray(String hexString) {
        int len = hexString.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return data;
    }
}
